﻿using System;
using System.Data;
using System.Data.Common;
using System.Globalization;
using System.Text;
using Kugar.Core.Data.DBCommon;
using Kugar.Core.ExtMethod;
using System.Data.SqlClient;
using System.Collections.Generic;
using Kugar.Core.ExtMethod;

#if SQL
namespace Kugar.Core.Data.MSSQLHelper
{

    public class SQLDataHelper : DbDatabaseHelperBase
    {
        public SQLDataHelper(string connString)
            : base(connString)
        {
        }

        public SQLDataHelper(DbConnection conn)
            : base(conn)
        {
        }

        /// <summary>获取当前数据库产品的版本号</summary>
        public string ProductVersion { get; private set; }

        #region "执行存储过程"

        public IEnumerable<T> ExecuteProcedureDataEntity<T>(string procName, Action<T, DbDataReader> afterPreRowBuild = null, Action<IEnumerable<T>, DbDataReader> afterAllRowBuild = null, bool? isThrowError = false, params SqlParameter[] param) where T : class ,new()
        {
            var cmd = ((SqlConnection)this.Connection).CreateCommand();

            cmd.CommandText = procName;

            if (param != null)
            {
                cmd.Parameters.AddRange(param);
            }

            cmd.CommandType = CommandType.StoredProcedure;

            return base.ExecuteDataEntity<T>(cmd,afterPreRowBuild,afterAllRowBuild, isThrowError);
        }

        public DataTable ExecuteProcedureDataTable(string procName, bool? isThrowError = false, params SqlParameter[] param)
        {
            var cmd = ((SqlConnection)this.Connection).CreateCommand();

            cmd.CommandText = procName;

            if (param != null)
            {
                cmd.Parameters.AddRange(param);
            }

            cmd.CommandType = CommandType.StoredProcedure;

            return base.ExecuteDataTable(cmd, isThrowError);
        }

        public int ExecuteProcedureNoQuery(string procName, bool? isThrowError = false, params SqlParameter[] param)
        {
            var cmd = ((SqlConnection) this.Connection).CreateCommand();

            cmd.CommandText = procName;

            if (param != null)
            {
                cmd.Parameters.AddRange(param);
            }

            cmd.CommandType=CommandType.StoredProcedure;

            return base.ExecuteNoQuery(cmd, isThrowError);
        }

        public T ExecuteProcedureScalar<T>(string procName, bool? isThrowError = false, params SqlParameter[] param)
        {
            var cmd = ((SqlConnection) this.Connection).CreateCommand();

            cmd.CommandType = CommandType.StoredProcedure;

            cmd.CommandText = procName;

            if (param!=null)
            {
                cmd.Parameters.AddRange(param);
            }

            return base.ExecuteScalar<T>(cmd, isThrowError);
        }


        #endregion

        /// <summary>
        ///     读取数据库中的存储过程
        /// </summary>
        /// <param name="isRefresh">是否强制刷新配置</param>
        public void LoadAllProcedure(bool isRefresh=false)
        {
            if (SQLProcdureCache.ContainsDB(Connection.Database) && !isRefresh)
            {
                return;
            }
            else
            {
                Dictionary<string, SqlParameter[]> v;
                SQLProcdureCache.TryRemove(Connection.Database, out v);
                LoadAllProcedureInternal();
            }
        }

        private SqlParameter[] emptyParamters=new SqlParameter[0];
        private void LoadAllProcedureInternal()
        {
            const string sqlGetParam =
                "SELECT * FROM information_schema.parameters WHERE specific_name =@paramName ORDER BY ORDINAL_POSITION";

            var procTable = base.ExecuteDataTable("select name from  sysobjects  where xtype='P' ORDER BY crdate");

            if (procTable!=null && procTable.Rows.Count>0)
            {
                var procDic = new Dictionary<string, SqlParameter[]>(procTable.Rows.Count,StringComparer.CurrentCultureIgnoreCase);

                var cmd = CreateCommand();

                cmd.CommandText = sqlGetParam;
                cmd.AddParameter("@paramName", DbType.String, "");

                var paramList=new List<SqlParameter>();

                for (int i = 0; i < procTable.Rows.Count; i++)
                {
                    var row = procTable.Rows[i];

                    cmd.Parameters.SetValue("@paramName", row["name"].ToStringEx());

                    var paramTable=ExecuteDataTable(cmd, false);
                    paramList.Clear();
                    if (!paramTable.IsEmptyData())
                    {
                        for (int j = 0; j < paramTable.Rows.Count; j++)
                        {
                            var paramRow = paramTable.Rows[j];

                            var param = new SqlParameter();
                            param.ParameterName = paramRow["PARAMETER_NAME"].ToStringEx();
                            param.SqlDbType = (SqlDbType)Enum.Parse(typeof(SqlDbType), paramRow["DATA_TYPE"].ToStringEx(), true);

                            var diction = paramRow["PARAMETER_MODE"].ToStringEx().ToUpper();

                            switch (diction)
                            {
                                case "IN":
                                     param.Direction= ParameterDirection.Input;
                                     break;
                                case "INOUT":
                                    param.Direction = ParameterDirection.InputOutput;
                                    break;
                                case "OUT":
                                    param.Direction = ParameterDirection.Output;
                                    break;
                                case "RETURN":
                                    param.Direction = ParameterDirection.ReturnValue;
                                    break;
                            }

                            var len = paramRow["CHARACTER_MAXIMUM_LENGTH"];
                            param.Size=len is DBNull?0:(int)len;

                            paramList.Add(param);
                        }

                        procDic.Add(row["name"].ToStringEx(), paramList.ToArray());
                    }
                    else
                    {
                        procDic.Add(row["name"].ToStringEx(), emptyParamters);
                    }

                    
                }

                SQLProcdureCache.TryAdd(this.Connection.Database, procDic);
            }


        }

        /// <summary>
        ///     使用存储过程名，获取参数列表
        /// </summary>
        /// <param name="procName">要获取参数列表的存储过程名</param>
        /// <returns>按参数顺序，返回参数列表</returns>
        public  SqlParameter[] GetProcedureParameters(string procName)
        {
            var dic = SQLProcdureCache.GetByDBName(Connection.Database);

            SqlParameter[] parameters;

            if (dic.TryGetValue(procName.Trim(' ','[',']'),out parameters))
            {
                if (parameters !=null && parameters.Length >0)
                {
                    var templist = new SqlParameter[parameters.Length];

                    for (int i = 0; i < parameters.Length; i++)
                    {
                        templist[i] = parameters[i].Copy();
                    }

                    return templist;
                }
                else
                {
                    return new SqlParameter[0];
                }
            }
            else
            {
                throw new Exception("未找到指定名称的存储过程，如果数据库已更改，请执行RefreshProc刷新配置");
            }
        }


        protected override void OpenConnection()
        {
            if (Connection != null)
            {
                if (Connection.State == ConnectionState.Closed)
                {
                    try
                    {
                        Connection.Open();
                    }
                    catch (Exception)
                    {

                        throw;
                    }
                }

            }
            else
            {
                if (ConnectionString.IsNullOrEmpty())
                {
                    throw new NoNullAllowedException("连接字符串不能为空");
                }

                Connection = new SqlConnection();

                Connection.ConnectionString = ConnectionString;

                Connection.Open();

            }

            if (string.IsNullOrEmpty(ProductVersion))
            {
                ProductVersion = this.Connection.ServerVersion; //; ExecuteScalar("select serverproperty(''ProductVersion'')").ToString();
            }

            MasterProductVersion =
                int.Parse(
                    ProductVersion.Substring(0, ProductVersion.IndexOf(".", StringComparison.OrdinalIgnoreCase)),
                    CultureInfo.InvariantCulture);



        }


        protected override void ExecuteDataTableInternal(DbCommand cmd, DataTable tbl)
        {
            var da = new SqlDataAdapter((SqlCommand)cmd);
            if (this.trans != null)
            {
                cmd.Transaction = trans;
            }
            tbl.RemotingFormat = SerializationFormat.Binary;

            try
            {
                da.Fill(tbl);
            }
            catch
            {
                throw;
            }
            finally
            {
                cmd.Transaction = null;
                cmd.Connection = null;
                cmd.Dispose();

                da.Dispose();
            }

        }


        protected override void ExecuteDataSetInternal(DbCommand cmd, DataSet ds)
        {
            var da = new SqlDataAdapter((SqlCommand)cmd);

            if (this.trans != null)
            {
                cmd.Transaction = trans;
            }

            ds.RemotingFormat = SerializationFormat.Binary;
            try
            {
                da.Fill(ds);
            }
            finally
            {
                cmd.Transaction = null;
                cmd.Connection = null;
                cmd.Dispose();

                da.Dispose();
            }

        }

        /// <summary>
        ///     获取当前连接的SPID值
        /// </summary>
        /// <returns></returns>
        public int GetCurrentSPID()
        {
            const string sql = @"select  @@SPID";

            try
            {
                var t = this.ExecuteScalar(sql);

                return (int)t;
            }
            catch (Exception)
            {
                return -1;
            }

        }

        public void Backup(DBBackupType backupType, string backupPath, string dbName)
        {
            /*
             * 语句中,{0} 为备份类型,当使用 Log时,该值为 log,其他时为 database
             *            {1} 为备份的数据库名称
             *            {2} 为备份的路径
             *            {3} 为当使用差异备份的时候,该值为:DIFFERENTIAL,其余为空
             */
            const string str = "backup  {0}  {1}   to disk='{2}' with '{3}' INIT";

            if (dbName.IsNullOrEmpty())
            {
                dbName = this.Connection.Database;
            }

            var sql = string.Format(str,
                                    backupType == DBBackupType.Log ? "log" : "database",
                                    dbName,
                                    backupPath,
                                    backupType == DBBackupType.DF ? "DIFFERENTIAL" : "");

            try
            {
                this.ExecuteNoQuery(sql);
            }
            catch (Exception)
            {

            }

        }

        public void RestoreDatabase(DBBackupType backupType, string filePath)
        {

        }

        /// <summary>
        ///     清空指定的数据库
        /// </summary>
        public void CleanDatabase()
        {
            this.CleanDatabase(string.Empty);
        }

        /// <summary>
        ///     清空指定的数据库
        /// </summary>
        public void CleanDatabase(string dbName)
        {
            if (this.MasterProductVersion > 9)
            {
                cleanSQL2005And2008(dbName);
            }
            else
            {
                cleanSQL2000(dbName);
            }
        }

        private void cleanSQL2005And2008(string dbName)
        {
            #region ""

            const string cleanSql = @"
                                                    declare @s int;
                                                    declare @tempStr varchar(50)

                                                    declare cursorSPID cursor for
                                                        select spid from master.sys.sysprocesses where  spid<>@@SPID and [dbid]=(select db_id('{0}'))                                                        

                                                    OPEN cursorSPID
                                                    FETCH cursorSPID INTO @s
                                                    WHILE(@@fetch_status = 0)
                                                    BEGIN
                                                        set @tempStr='kill '+RTRIM(@s)
                                                        BEGIN TRY
                                                            exec @tempStr
                                                        END TRY
                                                        BEGIN CATCH

                                                        END CATCH;
                                                                    
                                                        FETCH cursorSPID INTO @s
                                                    END
                                                    CLOSE cursorSPID
                                                    DEALLOCATE cursorSPID                                                                                                       
                                                    
                                                    use {0}
                                                    DECLARE @tablename varchar(50)
                                                    DECLARE @truncatesql varchar(255)
                                                    DECLARE TrCun_Cursor CURSOR FOR
                                                    select [name] from sysobjects where type = 'U' 
                                                    --有条件的清空表 name<>'不想清空的表名'--
                                                    OPEN TrCun_Cursor
                                                    FETCH TrCun_Cursor INTO @tablename
                                                    WHILE(@@fetch_status = 0)
                                                            BEGIN
                                                                SET @truncatesql = ' truncate table ' + @tablename
                                                                BEGIN TRY
                                                                    exec(@truncatesql)
                                                                END TRY
                                                                BEGIN CATCH

                                                                END CATCH;
                                                                FETCH TrCun_Cursor INTO @tablename
                                                            END
                                                    CLOSE TrCun_Cursor
                                                    DEALLOCATE TrCun_Cursor";

            #endregion

            var tempDBName = dbName.IsNullOrEmpty() ? this.Connection.Database : dbName;

            try
            {
                this.RollbackTransaction();
                this.BeginTransaction();
                this.ExecuteNoQuery(cleanSql, tempDBName);
            }
            catch (Exception)
            {

            }
            finally
            {
                this.CommitTransaction();
            }

        }

        private void cleanSQL2000(string dbName)
        {
            this.RollbackTransaction();

            var tempDBName = dbName.IsNullOrEmpty() ? this.Connection.Database : dbName;

            //断开所有链接
            var spidTbl = this.ExecuteDataTable("select spid from master..sysprocesses where  spid<>@@SPID and [dbid]=(select db_id('{0}'))",
                                  tempDBName);
            using (spidTbl)
            {
                if (!spidTbl.IsEmptyData())
                {
                    for (int i = 0; i < spidTbl.Rows.Count; i++)
                    {
                        var row = spidTbl.Rows[i];

                        try
                        {
                            this.ExecuteNoQuery(" Kill {0}", row[0].ToString());
                        }
                        catch (Exception)
                        {
                            continue;
                        }
                    }
                }
            }


            //清除表数据
            var tblNameTbl =
                    this.ExecuteDataTable(@"use {0}
                                                            select [name] from sysobjects where type = 'U' ",
                                                        tempDBName);

            try
            {
                this.BeginTransaction();
                using (tblNameTbl)
                {
                    if (!tblNameTbl.IsEmptyData())
                    {

                        for (int i = 0; i < tblNameTbl.Rows.Count; i++)
                        {
                            var row = tblNameTbl.Rows[i];

                            try
                            {
                                this.ExecuteNoQuery(" truncate table {0}", row[0].ToString());
                            }
                            catch (Exception)
                            {
                                continue;
                            }
                        }

                    }
                }

                this.CommitTransaction();
            }
            catch (Exception)
            {
                this.RollbackTransaction();
            }




        }

        #region "数据库结构函数"

        private const string getAllTableNameSql = @"select name from sysobjects where xtype='u'";
        public override string[] GetAllTableNames()
        {
            var nameList = new List<string>();

            using (var dr = ExecuteReader(getAllTableNameSql))
            {
                if (!dr.HasRows)
                {
                    return null;
                }

                while (dr.Read())
                {
                    nameList.Add(dr.GetString(1));
                }
            }

            return nameList.ToArray();
        }

        public override DataTable GetDatabaseTableSchema(string srcTableName, SchemaType schemaType)
        {
            if (srcTableName.IsNullOrEmpty())
            {
                throw new NoNullAllowedException("源表名不能为空");
            }

            var sqlstr = string.Format(getSchemaSqlstr, srcTableName);

            var da = new SqlDataAdapter(sqlstr, (SqlConnection)Connection);

            var tbl = new DataTable(srcTableName);

            da.FillSchema(tbl, schemaType);

            return tbl;
        }

        private const string getSchemaSqlstr = @"select top 1 * from {0}";
        public override DataSet GetDatabaseAllTableSchema(SchemaType schemaType)
        {
            var nameList = GetAllTableNames();

            if (nameList.IsEmptyData())
            {
                return null;
            }

            SqlCommand cmd = (SqlCommand)Connection.CreateCommand();
            var da = new SqlDataAdapter(cmd);
            var ds = new DataSet("tableSchema");
            foreach (string tableName in nameList)
            {
                var sqlstr = string.Format(getSchemaSqlstr, tableName);

                cmd.CommandText = sqlstr;

                var tbl = new DataTable(tableName);

                da.FillSchema(tbl, schemaType);

                ds.Tables.Add(tbl);
            }

            return ds;
        }

        #endregion

        public int MasterProductVersion { get; private set; }


        #region "分页操作"

        protected override string BuildPagingSql(PagingArgs args)
        {
            switch (MasterProductVersion)
            {
                case 8:
                    return BuildPagingSql_Sql2000(args, "");
                case 9:
                case 10:
                    return BuildPagingSql_Sql2005(args, "");
                default:
                    throw new NotSupportedException("不支持该数据库版本");
            }
        }

        protected override string BuildGetRecordCountSql(PagingArgs args)
        {
            const string sqlstrWithSelect = @"Select count(*) 
                                                 from 
                                                 (
                                                        {0}
                                                )  f
                                                ";

            const string sqlstrNoSelect = @"Select count(*) 
                                                 from {0}
                                                ";


            if (!args.TableSql.Trim().ToLower().StartsWith("select"))
            {
                return string.Format(sqlstrNoSelect, args.TableSql);
            }
            else
            {
                return string.Format(sqlstrWithSelect, args.TableSql);
            }


        }

        private string BuildPagingSql_Sql2000(PagingArgs args, string alias)
        {
            if (string.IsNullOrEmpty(alias))
            {
                alias = "tmp" + DateTime.Now.ToString("yyyyMMddHHmmss");
            }

            bool isTableName = IsTableName(args.TableSql.Trim());
            string orderSql = CreateOrderSql(args.OrderSql, args.KeyField);

            StringBuilder sb = new StringBuilder();
            if (isTableName)
            { //只输入简单的表名，视图等
                args.RecordCount = ExecuteScalar("select count(1) from {0} {2} {1}",
                    args.TableSql,
                    string.IsNullOrEmpty(args.WhereSql) ? string.Empty : string.Format(" where {0}", args.WhereSql),
                    alias).ToInt32();

                //确保PageIndex在有效范围
                args.EnsurePageIndex();

                //构造分页
                if (args.RecordCount == 0)
                { //没有记录
                    sb.AppendLineEx("select {0} from {1} WHERE 1=2", args.ColumnSql, args.TableSql);
                }
                else
                {
                    sb.AppendLineEx("select top {0} {1} from {2} {3} ", args.PageSize, args.ColumnSql, args.TableSql, alias);
                    sb.AppendLine("where ");
                    if (!string.IsNullOrEmpty(args.WhereSql)) sb.AppendLineEx("{0} and ", args.WhereSql);
                    sb.AppendLine("not exists (select null from ( ");
                    sb.AppendLineEx("select top {0} {1} from {2} ", args.PageSize * (args.PageIndex - 1), args.KeyField, args.TableSql);
                    if (!string.IsNullOrEmpty(args.WhereSql)) sb.AppendLineEx("where {0} ", args.WhereSql);
                    sb.AppendLineEx("order by {0} ", orderSql);
                    sb.AppendLineEx(") {1}_2 where {1}.{0}={1}_2.{0}) ", args.KeyField, alias);
                    sb.AppendLineEx("order by {0} ", orderSql);
                }
            }
            else
            { //传入的是sql语句
                args.RecordCount = ExecuteScalar("select count(1) from ({0}) {2} {1}",
                    args.TableSql,
                    string.IsNullOrEmpty(args.WhereSql) ? string.Empty : string.Format(" where {0}", args.WhereSql),
                    alias).ToInt32();

                //确保PageIndex在有效范围
                args.EnsurePageIndex();

                //构造分页
                if (args.RecordCount == 0)
                {
                    sb.AppendFormat("select {0} from ({1}) {2} where 1=2", args.ColumnSql, args.TableSql, alias);
                }
                else
                {
                    sb.AppendLineEx("select top {0} {1} from ({2}) {3} ", args.PageSize, args.ColumnSql, args.TableSql, alias);
                    sb.AppendLine("where ");
                    if (!string.IsNullOrEmpty(args.WhereSql)) sb.AppendLineEx(" ({0}) and ", args.WhereSql);
                    sb.AppendLine("not exists (select null from ( ");
                    sb.AppendLineEx("select top {0} {1} from ({2}) {3}_3 ", args.PageSize * (args.PageIndex - 1), args.KeyField, args.TableSql, alias);
                    if (!string.IsNullOrEmpty(args.WhereSql)) sb.AppendLineEx("where {0} ", args.WhereSql);
                    sb.AppendLineEx("order by {0} ", orderSql);
                    sb.AppendLineEx(") {1}_2 where {1}.{0}={1}_2.{0}) ", args.KeyField, alias);
                    sb.AppendLineEx("order by {0} ", orderSql);
                }
            }

            return sb.ToString();
        }

        private string BuildPagingSql_Sql2005(PagingArgs args, string alias)
        {
            if (string.IsNullOrEmpty(alias))
            {
                alias = "tmp" + DateTime.Now.ToString("yyyyMMddHHmmss");
            }

            bool isTableName = IsTableName(args.TableSql.Trim());
            string orderSql = CreateOrderSql(args.OrderSql, args.KeyField);

            StringBuilder sb = new StringBuilder();

            if (isTableName)
            {
                args.RecordCount = ExecuteScalar("select count(1) from {0} {2} {1}",
                    args.TableSql,
                    string.IsNullOrEmpty(args.WhereSql) ? string.Empty : string.Format(" where {0}", args.WhereSql),
                    alias).ToInt32();

                //确保PageIndex在有效范围
                args.EnsurePageIndex();

                //构造分页
                sb.AppendLineEx("with _t1_ as (");
                sb.AppendLineEx("select row_number() over ( order by {0}) as row_number,{1} from {2} {3}", orderSql, args.ColumnSql, args.TableSql, alias);
                if (!string.IsNullOrEmpty(args.WhereSql)) sb.AppendLineEx("where ( {0} )", args.WhereSql);
                sb.AppendLineEx(") select {0} from _t1_", args.ColumnSql);
                sb.AppendLineEx("where row_number between {0} and {1}",
                    (args.PageIndex - 1) * args.PageSize + 1,
                    args.PageIndex * args.PageSize);
            }
            else
            {
                args.RecordCount = ExecuteScalar("select count(1) from ({0}) {2} {1}",
                    args.TableSql,
                    string.IsNullOrEmpty(args.WhereSql) ? string.Empty : string.Format(" where {0}", args.WhereSql),
                    alias).ToInt32();

                //确保PageIndex在有效范围
                args.EnsurePageIndex();

                sb.AppendLineEx("with _t1_ as (");
                sb.AppendLineEx("select row_number() over ( order by {0}) as row_number,{1} from ({2}) {3}", orderSql, args.ColumnSql, args.TableSql, alias);
                if (!string.IsNullOrEmpty(args.WhereSql)) sb.AppendLineEx("where {0}", args.WhereSql);
                sb.AppendLineEx(") select {0} from _t1_", args.ColumnSql);
                sb.AppendLineEx("where row_number between {0} and {1}",
                    (args.PageIndex - 1) * args.PageSize + 1,
                    args.PageIndex * args.PageSize);
            }

            return sb.ToString();
        }

        #endregion

        private static bool IsTableName(string tableSql)
        {
            return !tableSql.StartsWith("select", StringComparison.OrdinalIgnoreCase); //  s_RegexTableName.IsMatch(value);
        }

        //构建排序语句
        private static string CreateOrderSql(string orderSql, string keyField)
        {
            if (string.IsNullOrEmpty(keyField)) throw new ArgumentException("必须设置keyField", keyField);
            string[] keyFields = keyField.Split(',');

            if (string.IsNullOrEmpty(orderSql))
            {
                StringBuilder sb = new StringBuilder();
                for (int i = 0; i < keyFields.Length; ++i)
                {
                    if (i != 0) sb.Append(",");
                    sb.AppendFormat("{0} asc", keyFields[i]);
                }
                return sb.ToString();
            }
            else
            {
                StringBuilder sb = new StringBuilder();
                sb.Append(orderSql);
                foreach (var field in keyFields)
                {
                    if (!orderSql.Contains(field))
                    {
                        sb.AppendFormat(",{0} asc", field);
                    }
                }
                return sb.ToString();
            }
        }




        private static class SQLProcdureCache
        {
            private static Dictionary<string, Dictionary<string, SqlParameter[]>> _cache = new Dictionary<string, Dictionary<string, SqlParameter[]>>(5, StringComparer.CurrentCultureIgnoreCase);
            private static object _lockObj = new object();

            public static bool TryAdd(string dbName, Dictionary<string, SqlParameter[]> procList)
            {
                lock (_lockObj)
                {
                    if (_cache.ContainsKey(dbName))
                    {
                        return false;
                    }
                    else
                    {
                        _cache.Add(dbName, procList);
                        return true;
                    }
                }
            }

            public static bool TryRemove(string dbName, out Dictionary<string, SqlParameter[]> procList)
            {
                lock (_lockObj)
                {
                    if (_cache.ContainsKey(dbName))
                    {
                        procList = _cache[dbName];
                        return true;
                    }
                    else
                    {
                        procList = null;
                        return false;
                    }
                }
            }

            public static Dictionary<string, SqlParameter[]> GetByDBName(string dbName)
            {
                Dictionary<string, SqlParameter[]> v = null;

                if (_cache.TryGetValue(dbName, out v))
                {
                    return v;
                }
                else
                {
                    return null;
                }
            }

            public static bool ContainsDB(string dbName)
            {
                return _cache.ContainsKey(dbName);
            }
        }

    }

    public enum DBBackupType
    {
        /// <summary>
        ///     完全备份
        /// </summary>
        DB,

        /// <summary>
        ///     差异备份
        /// </summary>
        DF,

        /// <summary>
        ///     日志备份
        /// </summary>
        Log
    }
}
#endif


